/*
 * @Author: hongbin
 * @Date: 2022-09-04 19:39:45
 * @LastEditors: hongbin
 * @LastEditTime: 2022-11-30 10:59:15
 * @Description:宇宙中固定的对象
 */
import THREE from ".";
import { acterScaleMultiple } from "../constants";
import { animationControl } from "./helper";
import { RandomColor, PatternLog } from "./utils";
import { initGUI } from "./utils/gui";

export const acterWrap = new THREE.Group();
acterWrap.name = "acterWrap";
acterWrap.scale.set(acterScaleMultiple, acterScaleMultiple, acterScaleMultiple);
acterWrap.position.y += 10;

/**
 * 提供一个基本的人物模型模版 供创建更多人物模型
 */
export const acterWrapTemplate = new THREE.Group();

export const cameraWrap = new THREE.Group();
cameraWrap.name = "cameraWrap";

export const setActerPosition = (v: THREE.Vector3) => {
    acterWrap.position.copy(v);
    cameraWrap.position.copy(v);
};

export const setActerRotate = (angle: THREE.Vector3) => {
    acterWrap.rotation.setFromVector3(angle);
    cameraWrap.rotation.setFromVector3(angle);
};

/**
 * 初始化webGL 渲染器
 */
export const initWebGLRenderer = (parameters?: THREE.WebGLRendererParameters) => {
    const renderer = new THREE.WebGLRenderer(parameters);
    // renderer.setPixelRatio(window.devicePixelRatio);
    //TODO 开发时使用低分辨率 减小本地卡顿
    renderer.setPixelRatio(1);
    renderer.setSize(window.innerWidth, window.innerHeight);
    //阴影开启
    // renderer.shadowMap.enabled = true;
    //阴影类型
    // renderer.shadowMap.type = THREE.PCFShadowMap;
    // renderer.outputEncoding = THREE.sRGBEncoding;
    window.renderer = renderer;
    return renderer;
};

function RenderControl() {
    let render = () => {};
    let handle = 0;

    /**
     * 设置在解除鼠标锁定时的渲染-不进行碰撞检测 只渲染
     */
    function setRender(call: VoidFunction) {
        render = call;
    }

    function everyFrame() {
        render();

        handle = requestAnimationFrame(everyFrame);
    }

    function stop() {
        cancelAnimationFrame(handle);
    }
    return { setRender, everyFrame, stop };
}

export const renderControl = RenderControl();

const initCamera = () => {
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 3000);
    camera.name = "camera";
    camera.position.set(0, 10 * acterScaleMultiple, 40 * acterScaleMultiple);
    cameraWrap.add(camera);
    cameraWrap.position.set(0, 10, 0);
    return camera;
};

export const hemisphereLight = new THREE.HemisphereLight(0x5511ff, 0xffffff, 1);
const initLights = () => {
    hemisphereLight.position.set(-3, 2.4, 0);

    window.gui
        .addColor({ c: "#5511ff" }, "c")
        .name("半球光颜色")
        .onChange((c) => {
            console.log(c);
            hemisphereLight.color = new THREE.Color(c);
            window.render();
        });

    return [hemisphereLight];
};

export const scene = new THREE.Scene();

export const intGlobalVariable = () => {
    window._vector3 = new THREE.Vector3();
    window.PatternLog = PatternLog;
    initGUI().add(
        {
            当前位置: () => {
                console.log(acterWrap.position);
                console.log(acterWrap, cameraWrap);
            },
        },
        "当前位置"
    );
    window.acterWrap = acterWrap;
};

/**
 * scene的背景颜色和雾的颜色一致
 * 雾由浓到淡
 */
const sceneFog = () => {
    scene.background = new RandomColor();
    const fog = new THREE.FogExp2(scene.background as ignore, 0.004);
    scene.fog = fog;
    window.gui.add(scene.fog, "density", 0, 0.004).onChange(window.render);
    //雾由浓到淡
    animationControl.add(
        (() => {
            const part = 90;
            const pace = (0.004 - 0.0005) / part;

            return {
                count: 0,
                part,
                callback: function () {
                    fog.density -= pace;
                    this.count++;
                },
            };
        })()
    );
};

/**
 * 初始化环境 阳光 相机
 */
export const initScene = () => {
    const camera = initCamera();
    const lights = initLights();

    scene.add(...lights, cameraWrap, acterWrap);
    sceneFog();
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        window.renderer.setSize(window.innerWidth, window.innerHeight);
        render();
    }

    window.addEventListener("resize", onWindowResize);

    function render(e?: number) {
        e && console.log(e);
        window.renderer?.render(scene, camera);
    }

    window.render = render;
};
